#pragma once
#include "../Comm/comm.hpp"
#include "../Comm/util.hpp"
#include "../Comm/log.hpp"
#include "include/mysql.h"

namespace ns_model
{
    using namespace ns_util;
    using namespace ns_log;

    class Question
    {
    public:
        std::string _number; // 题目编号
        std::string _title;  // 题目标题
        std::string _star;   // 题目难度
        std::string _desc;   // 题目的描述
        std::string _header; // 题目的代码区域
        std::string _tail;   // 题目的测试用例
        int _cpu_limit;      // 题目的CPU限制
        int _mem_limit;      // 题目的内存限制
    };

    class Model
    {
    public:
        Model() {}
        ~Model() {}

        const std::string table_name = "oj_questions";
        const std::string host = "127.0.0.1";
        const std::string user = "oj_client";
        const std::string password = "1234";
        const std::string db = "oj";
        const unsigned int port = 8888;

    public:
        bool QueryMysql(const std::string &sql, std::vector<Question> *out)
        {
            // 1. 链接数据库
            MYSQL *my = mysql_init(nullptr);
            if (mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(),
                                   db.c_str(), port, nullptr, 0) == nullptr)
            {
                LOG(FATAL) << "mysql connect faild..." << std::endl;
                return false;
            }
            mysql_set_character_set(my, "utf8");
            LOG(INFO) << "mysql connect success..." << std::endl;

            // 2. 执行sql并获取结果
            // 2.1 执行sql
            int res = mysql_query(my, sql.c_str());
            if (res != 0)
            {
                LOG(WARNING) << "res: " << res << ", " << sql << " error" << std::endl;
                return false;
            }
            LOG(INFO) << "res: " << res << std::endl;

            // 2.2 获取执行结果
            // 2.2.1 mysql_store_result获取读取结果
            MYSQL_RES *my_result = mysql_store_result(my);
            // 2.2.2 mysql_num_rows获取结果行数
            my_ulonglong rows = mysql_num_rows(my_result);
            // 2.2.3 mysql_num_fields获取结果列数
            unsigned int cols = mysql_num_fields(my_result);
            // 2.2.4 mysql_fetch_fields获取列名称
            // MYSQL_FIELD *fields = mysql_fetch_fields(my_result);
            // for (int i = 0; i < cols; ++i)
            // {
            //     std::cout << fields[i].name << "\t";
            // }
            // std::cout << std::endl;

            // 2.2.5 mysql_fetch_row获取每一行的内容
            MYSQL_ROW line;
            Question q;
            for (int i = 0; i < rows; ++i)
            {
                line = mysql_fetch_row(my_result);
                q._number = line[0];
                q._title = line[1];
                q._star = line[2];
                q._desc = line[3];
                q._header = line[4];
                q._tail = line[5];
                q._cpu_limit = atoi(line[6]);
                q._mem_limit = atoi(line[7]);

                out->push_back(q);
            }

            // 3. 关闭数据库
            free(my_result);
            mysql_close(my);

            return true;
        }

        bool GetAllQuestions(std::vector<Question> *out)
        {
            std::string sql = "select * from ";
            sql += table_name;
            return QueryMysql(sql, out);
        }

        bool GetOneQuestion(const std::string &number, Question *q)
        {
            bool res = false;
            std::string sql = "select * from ";
            sql += table_name;
            sql += " where number=";
            sql += number;
            std::vector<Question> result;
            if (QueryMysql(sql, &result))
            {
                if (result.size() == 1)
                {
                    *q = result[0];
                    res = true;
                }
            }
            return res;
        }
    };
} // namespace ns_model
